package com.iot08.api.service;

import com.alibaba.fastjson.JSONObject;
import com.iot08.api.config.redis.RedisClusterService;
import com.iot08.api.service.supplement.KafkaService;
import com.iot08.api.vo.request.AppManagerReqVo;
import com.iot08.api.vo.request.base.BaseAccountReqVO;
import com.iot08.common.constant.ConstCacheField;
import com.iot08.common.constant.ConstKafka;
import com.iot08.common.entity.app.AppUidName;
import com.iot08.common.entity.app.Device;
import com.iot08.common.entity.app.DeviceAppManager;
import com.iot08.common.entity.app.DeviceCmsg;
import com.iot08.common.service.base.BaseService;
import com.iot08.common.utils.StringUtil;
import com.iot08.common.utils.response.ResponseEnum;
import com.iot08.common.utils.response.ResponseMap;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;


/**
 * @author cwj
 * @description App启禁应用管理
 * @date 2024/11/14 14:46
 **/
@Slf4j
@Service
public class DeviceAppManagerService extends BaseService<DeviceAppManager> {
    @Resource
    private KafkaService kafkaService;

    @Resource
    private RedisClusterService redisClusterService;

    @Resource
    @Lazy
    private DeviceService deviceService;


    /**
     * @description 根据IMEI查询设备的APP应用信息
     * @author cwj
     * @param [imei]
     * @return com.iot08.common.entity.app.DeviceAppManager
     * @date @time 2024/11/14 16:27
     **/
    public DeviceAppManager queryDeviceAppManagerByImei(String imei){
        Criteria criteria = Criteria.where("imei").is(imei);
        Query query = new Query(criteria).limit(1);
        return mongoTemplate.findOne(query, getTClass());
    }

    /**
     * @description 根据ID更新设备的APP应用信息
     * @author cwj
     * @param [id, update]
     * @return void
     * @date @time 2024/11/14 17:27
     **/
    public void upadteDeviceAppManagerById(String id,Update update){
        this.updateById(id,update);
    }


    /**
     * @description 根据IMEI查询设备的APP应用信息，如果没查到则下发通知设备上报信息
     * @author cwj
     * @param [imei]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2024/11/14 17:46
     **/
    public ResponseMap queryDeviceAppManager(String imei, BaseAccountReqVO vo){
        ResponseMap res = ResponseMap.success();
        Criteria criteria = Criteria.where("imei").is(imei);
        Query query = new Query(criteria).limit(1);
        DeviceAppManager deviceAppManager = this.findOne(query);
        if(!ObjectUtils.isEmpty(deviceAppManager)){
            res.put("id",deviceAppManager.getId());
            res.put("appUidNames",deviceAppManager.getAppUidNames());
        }else {
            res = ResponseMap.fail(ResponseEnum.STATUS400.getCode(),"API.request.ResponseMsg.DeviceAppManager");
            Device device = deviceService.findById(imei);
            //检查设备imei有无App应用监管相关指令
            String modules = device.getModules();
            if (StringUtil.isNotBlank(device.getWatchCustomFunction())) {
                modules = device.getWatchCustomFunction();
            }
            if (modules == null || (!modules.contains("M0")) ) {
                return res;
            }
            kafkaService.emitDeviceDemand(imei, ConstKafka.DEV_TYPE_ACTIVE_FN_INFO, new JSONObject(), vo.getOpenid());
        }
        return res;
    }

    /**
     * @description 设置应用监管
     * @author cwj
     * @param [imei, vo]
     * @return com.iot08.common.utils.response.ResponseMap
     * @date @time 2024/11/15 11:04
     **/
    public ResponseMap settingDeviceAppManager(String imei, AppManagerReqVo vo){
        //检查设备是否在线
        String onlineStatus = redisClusterService.hget(imei, ConstCacheField.ONLINE_STATUS);
        if (!"1".equals(onlineStatus)) {
            return ResponseMap.fail(ResponseEnum.STATUS5001.getCode(), ResponseEnum.STATUS5001.getMsg());
        }
        //检查App应用是否存在
        DeviceAppManager deviceAppManager = this.findById(vo.getId());
        if(ObjectUtils.isEmpty(deviceAppManager)){
           return ResponseMap.fail(ResponseEnum.STATUS410.getCode(),"API.request.dataNotExists");
        }else{
            List<AppUidName> appUidNames = deviceAppManager.getAppUidNames();
            //检查App应用是否已经卸载或不存在
            if(checkAppUidIsNotExists(vo.getAppUid(), appUidNames)){
                 return ResponseMap.fail(ResponseEnum.STATUS410.getCode(),"API.request.dataNotExists");
            } else {
                JSONObject kafkaJson = assembleKafakaJson(vo, deviceAppManager, appUidNames);
                //更新启禁用的状态
                updateAppmanager(vo, deviceAppManager);
                //发送开放/禁止App应用指令设置
                kafkaService.emitDeviceDemand(imei, ConstKafka.DEVICE_TYPE_DSAPPFN_DISABLE_OL, kafkaJson, vo.getOpenid());
            }
        }
        return ResponseMap.success();
    }

    /**
     * @description 清除应用监管数据
     * @author cwj
     * @param [imei]
     * @return void
     * @date @time 2025/7/8 17:55
     **/
    public void delByImei(String imei) {
        Query query = new Query(Criteria.where("imei").is(imei));
        mongoTemplate.remove(query,DeviceAppManager.class);
    }



    /**
     * @description 构建发送的kafka数据内容
     * @author cwj
     * @param [vo, deviceAppManager, appUidNames]
     * @return com.alibaba.fastjson.JSONObject
     * @date @time 2024/11/16 15:41
     **/
    private JSONObject assembleKafakaJson(AppManagerReqVo vo, DeviceAppManager deviceAppManager, List<AppUidName> appUidNames) {
        JSONObject kafkaJson = new JSONObject();
        kafkaJson.put("totalCount", deviceAppManager.getTotalCount());
        kafkaJson.put("elementCount",2);
        //组装指令内容
        kafkaJson.put("settingContent",assembleCommandContent(vo, appUidNames));
        return kafkaJson;
    }

    /**
     * @description 组装指令内容，设置APP应用的指令状态
     * @author cwj
     * @param [vo, appUidNames]
     * @return java.lang.StringBuilder
     * @date @time 2024/11/16 15:39
     **/
    private String assembleCommandContent(AppManagerReqVo vo, List<AppUidName> appUidNames) {
        StringBuilder contentStr = new StringBuilder();
        for(int i = 0; i< appUidNames.size(); i++){
            AppUidName aun = appUidNames.get(i);
            if(aun.getAppUid().equals(vo.getAppUid())){
                aun.setIsOpen(vo.getIsOpen());
            }
            contentStr.append(aun.getAppUid()).append(",").append(aun.getIsOpen());
            if(i< appUidNames.size()-1){
                contentStr.append(",");
            }
        }
        return contentStr.toString();
    }

    /**
     * @description 更新App启禁状态
     * @author cwj
     * @param [vo, deviceAppManager]
     * @return void
     * @date @time 2024/11/16 15:40
     **/
    private void updateAppmanager(AppManagerReqVo vo, DeviceAppManager deviceAppManager) {
        Query query = new Query(Criteria.where("_id").is(deviceAppManager.getId()).and("appUidNames.appUid").is(vo.getAppUid()));
        Update update = new Update();
        update.set("updateDate",new Date());
        update.set("appUidNames.$.isOpen", vo.getIsOpen());
        //更新App应用监控的指定内容
        this.update(query,update);
    }

    /**
     * @description
     * @author cwj
     * @param [vo, appUidNames]
     * @return boolean
     * @date @time 2024/11/16 15:30
     **/
    private boolean checkAppUidIsNotExists(String appUid, List<AppUidName> appUidNames) {
        int count = 0;
        for(int i = 0; i< appUidNames.size(); i++){
            AppUidName aun = appUidNames.get(i);
            if(!aun.getAppUid().equals(appUid)){
                count++;
            }else{
                break;
            }
        }
        return count == appUidNames.size();
    }
}
